﻿using System;
using System.Collections.Generic;
using System.Text;
using Seagull.BarTender.Print;
using System.Diagnostics;
using Seagull.BarTender.PrintServer;

namespace LabelPrintSystem
{
    class ClsZebraSdk
    {//BT  .NET SDK  添加引用 using  Seagull.BarTender.Print;
        #region event
        delegate bool DelFormatLoader(string formatName);

        public event EventHandler evt_show_log_handle;
        protected void On_evt_show_log_handle(object obj, EventArgs e)
        {
            if (this.evt_show_log_handle != null)
                this.evt_show_log_handle(obj, e);
        }
        public event EventHandler evt_complete_print_handle;
        protected void On_evt_complete_print_handle(object obj, EventArgs e)
        {
            if (this.evt_complete_print_handle != null)
                this.evt_complete_print_handle(obj, e);
        }
        public event EventHandler evt_get_engine_handle;
        protected void On_evt_get_engine_handle(object obj, EventArgs e)
        {
            if (this.evt_get_engine_handle != null)
                this.evt_get_engine_handle(obj, e);
        }
        public event EventHandler evt_complete_LoadFormat_handle;
        protected void On_evt_complete_LoadFormat_handle(object obj, EventArgs e)
        {
            if (this.evt_complete_LoadFormat_handle != null)
                this.evt_complete_LoadFormat_handle(obj, e);
        }
        #endregion

        private Engine engine = null; // The BarTender Print Engine
        private LabelFormatDocument format = null; // The currently open Format
        private const string appName = "Label Print";
        private ClsPrintInfo PrintInfo;
        public ClsZebraSdk(ClsPrintInfo PInfo)
        {
            this.PrintInfo = PInfo;
        }

        public bool iniEngine()
        {
            // Create and start a new BarTender Print Engine.
            try
            {
                engine = new Engine(true);
            }
            catch (PrintEngineException exception)
            {
                // If the engine is unable to start, a PrintEngineException will be thrown.
                On_evt_show_log_handle("Engine:无法打开\r\n" + exception.Message, new ClsEventMode() { evt_mode = ClsEventMode.en_evtMode.evt_err });
                //MessageBox.Show(this, exception.Message, appName);
                //this.Close(); // Close this app. We cannot run without connection to an engine.
                return false;
            }

            PrintInfo.PrinterName = new List<string>();
            // Get the list of printers
            Printers printers = new Printers();
            foreach (Printer printer in printers)
            {
                PrintInfo.PrinterName.Add(printer.PrinterName);
                // cboPrinters.Items.Add(printer.PrinterName);
            }
            if (printers.Count > 0)
            {
                // Automatically select the default printer.
                PrintInfo.DefaultPrinterName = printers.Default.PrinterName;
                // cboPrinters.SelectedItem = printers.Default.PrinterName;
            }
            On_evt_get_engine_handle(this.PrintInfo, null);
            return true;
        }

        public void FormatLoader()
        {
            DelFormatLoader loder = new DelFormatLoader(formatLoader_DoWork);
            loder.BeginInvoke(PrintInfo.SelectFormatName, formatLoader_RunWorkerCompleted, loder);
        }

        bool formatLoader_DoWork(string formatName)
        {
            string errorMessage = "";
            lock (engine)
            {// We lock the engine here because the engine might still be printing a format.
                try
                {
                    if (format != null)
                        format.Close(SaveOptions.DoNotSaveChanges);
                    format = engine.Documents.Open(formatName);
                    On_evt_show_log_handle(string.Format("模板打开:{0}", formatName), null);
                    return true;
                }
                catch (System.Runtime.InteropServices.COMException comException)
                {
                    errorMessage = String.Format("无法打开模板: {0}\n原因: {1}", formatName, comException.Message);
                    format = null;
                }
            }
            if (errorMessage.Length != 0)
            {
                On_evt_show_log_handle(errorMessage, new ClsEventMode() { evt_mode = ClsEventMode.en_evtMode.evt_err });
            }
            return false;
        }

        void formatLoader_RunWorkerCompleted(IAsyncResult result)
        {
            // We lock on the engine here so that if we have a valid format object
            // we don't lose it while we are using it.
            if ((result.AsyncState as DelFormatLoader).EndInvoke(result))
            {
                string IdenticalCopies = null;
                lock (engine)
                {
                    if (format != null)
                    {
                        //cboPrinters.SelectedItem = format.PrintSetup.PrinterName;

                        // Set the number of identical copies.
                        if (format.PrintSetup.SupportsIdenticalCopies == false)
                        {
                            //PrintInfo.IdenticalCopies = null;
                        }
                        else
                        {
                            //PrintInfo.IdenticalCopies = format.PrintSetup.IdenticalCopiesOfLabel.ToString();
                            IdenticalCopies = format.PrintSetup.IdenticalCopiesOfLabel.ToString();
                        }

                        // Set the number of serialized copies.
                        if (format.PrintSetup.SupportsSerializedLabels == false)
                        {
                            PrintInfo.SerializedCopies = null;
                        }
                        else
                        {
                            PrintInfo.SerializedCopies = format.PrintSetup.NumberOfSerializedLabels.ToString();
                        }

                        // Set the substrings grid.
                        if (format.SubStrings.Count > 0)
                        {
                            PrintInfo.FormatSubStrings = new Dictionary<string, string>();
                            foreach (SubString sub in format.SubStrings)
                            {
                                PrintInfo.FormatSubStrings.Add(sub.Name, sub.Value);
                            }
                            //BindingSource bindingSource = new BindingSource();
                            //bindingSource.DataSource = format.SubStrings;
                            //substringGrid.DataSource = bindingSource;
                            //substringGrid.AutoResizeColumns();
                            //lblNoSubstrings.Visible = false;
                        }
                        else
                        {
                            PrintInfo.FormatSubStrings = null;
                            // lblNoSubstrings.Visible = true;
                        }
                        //   substringGrid.Invalidate();
                    }
                }
                string str = string.Format("IdenticalCopies:{0}\r\nSerializedCopies:{1}\r\n", IdenticalCopies == null ? "null" : IdenticalCopies, PrintInfo.SerializedCopies == null ? "null" : PrintInfo.SerializedCopies);
                if (PrintInfo.FormatSubStrings != null)
                {
                    str += "FormatSubStrings:\r\n";
                    foreach (string key in PrintInfo.FormatSubStrings.Keys)
                    {
                        str += string.Format("-->{0}:{1}\r\n", key, PrintInfo.FormatSubStrings[key]);
                    }
                    str = str.Substring(0, str.Length - 2);
                }
                else
                {
                    str += string.Format("FormatSubStrings:\r\n-->null");
                }
                On_evt_show_log_handle(str, null);
                On_evt_complete_LoadFormat_handle(PrintInfo, null);
            }
            else
            {
                On_evt_show_log_handle("Unable to open format", new ClsEventMode() { evt_mode = ClsEventMode.en_evtMode.evt_err });
            }
        }

        public void PrintLabel(int IdenticalCopies = 1, int SerializedCopies = 1)
        {
            // We lock on the engine here so we don't lose our format object
            // if the user were to click on a format that wouldn't load.
            lock (engine)
            {
                if (format != null)
                {
                    //string aaa = format.PrintSetup.Performance.AllowGraphicsCaching.ToString();
                    //aaa = format.PrintSetup.Performance.AllowFormatCaching.ToString();
                    //aaa = format.PrintSetup.Performance.AllowStaticGraphics.ToString();
                    //aaa = format.PrintSetup.Performance.AllowStaticObjects.ToString();
                    //format.PrintSetup.Performance.AllowFormatCaching = true ;
                    On_evt_show_log_handle("PrintSet", null);
                    bool success = true;
                    // Assign number of identical copies if it is not datasourced.
                    if (format.PrintSetup.SupportsIdenticalCopies)
                    {
                        format.PrintSetup.IdenticalCopiesOfLabel = Convert.ToInt32(PrintInfo.IdenticalCopies);
                        On_evt_show_log_handle("IdenticalCopies: " + format.PrintSetup.IdenticalCopiesOfLabel, null);
                    }
                    else
                    {
                        On_evt_show_log_handle("IdenticalCopies: null", null);
                    }
                    // Assign number of serialized copies if it is not datasourced.
                    if (format.PrintSetup.SupportsSerializedLabels)
                    {
                        format.PrintSetup.NumberOfSerializedLabels = SerializedCopies;
                        On_evt_show_log_handle("SerializedCopies: " + format.PrintSetup.NumberOfSerializedLabels, null);
                    }
                    else
                    {
                        On_evt_show_log_handle("SerializedCopies: null", null);
                    }

                    // Set the substrings grid.
                    if (format.SubStrings.Count > 0)
                    {
                        /* 2017/11/27  二维码里面的信息不允许加入前缀和后缀，否则substring获取的是加了前缀和后缀的信息，设定setsubstring后模板会自动再次加入后缀，导致信息重复，处理方法：模板将前缀后缀直接放到嵌入数据框内，或者改用VB脚本的方式生成二维码信息
                         * */
                        if (PrintInfo.FormatSubStringsChange != null)
                        {
                            string str = "FormatSubStringsChange:\r\n";
                            foreach (string key in PrintInfo.FormatSubStringsChange.Keys)
                            {
                                format.SubStrings.SetSubString(key, PrintInfo.FormatSubStringsChange[key].ToString());
                                str += string.Format("-->{0}:{1}\r\n", key, PrintInfo.FormatSubStringsChange[key]);
                            }
                            str = str.Substring(0, str.Length - 2);

                            //PrintInfo.FormatSubStrings = new Dictionary<string, string>();
                            //foreach (SubString sub in format.SubStrings)
                            //{
                            //    PrintInfo.FormatSubStrings.Add(sub.Name, sub.Value);
                            //}

                            On_evt_show_log_handle(str, null);
                        }
                    }
                    else
                    {
                        On_evt_show_log_handle("FormatSubStrings:\r\n-->null", null);
                    }

                    // If there are no incorrect values in the copies boxes then print.
                    if (success)
                    {
                        // Get the printer from the dropdown and assign it to the format.
                        if (PrintInfo.SelectPrinterName != null && PrintInfo.SelectPrinterName != "")
                            format.PrintSetup.PrinterName = PrintInfo.SelectPrinterName;
                        On_evt_show_log_handle(string.Format("PrinterName:{0}", format.PrintSetup.PrinterName), null);
                        Messages messages;
                        int waitForCompletionTimeout = 5000; // 5 seconds
                        Result result = format.Print(appName, waitForCompletionTimeout, out messages);
                        string messageString = "\n\nMessages:";

                        ////清除打印任务队列--测试2017/11/1，能否修复首次打印长时间等待bug
                        //using (TaskManager btTaskManager = new TaskManager())
                        //{
                        //    btTaskManager.TaskQueue.Clear();
                        //}



                        foreach (Seagull.BarTender.Print.Message message in messages)
                        {
                            messageString += "\n\n" + message.Text;
                        }

                        if (result == Result.Failure)
                        {
                            On_evt_show_log_handle("打印失败", new ClsEventMode() { evt_mode = ClsEventMode.en_evtMode.evt_err });
                        }
                        else
                            On_evt_show_log_handle("打印成功", null);
                    }
                }
                On_evt_complete_print_handle(null, null);
            }
        }

        public void StartPrint()
        {

        }

        public void StopPrint()
        {
            // Quit the BarTender Print Engine, but do not save changes to any open formats.
            if (engine != null)
                engine.Stop(SaveOptions.DoNotSaveChanges);
            //On_evt_show_log_handle("Engine Stop", null);
        }

        public void EngineVisible(bool isVisible, string labelName)
        {//将模板显示给用户，用次方法有BUG，再次使用会导致软件闪退，改用进程打开模板的方式--> OpenFormatProcsss
            lock (engine)
            {
                //if (engine == null) return;
                engine.Window.Visible = false;
                // engine.Documents.CloseAll(SaveOptions.DoNotSaveChanges);
                if (labelName != null)
                {
                    engine.Documents.Open(labelName);
                    engine.Window.Visible = isVisible;
                }
            }
        }

        public void OpenFormatProcsss(string labelFormatName)
        {
            try
            {
                System.Diagnostics.Process.Start(labelFormatName);
                On_evt_show_log_handle("模板已在Bartender软件打开,请查看下方任务栏BT软件", new ClsEventMode(ClsEventMode.en_evtMode.evt_Tips));
            }

            catch (Exception ex)
            {
                On_evt_show_log_handle(string.Format("Unable to open format:{0}", ex.ToString()), new ClsEventMode() { evt_mode = ClsEventMode.en_evtMode.evt_err });
            }
        }

    }
}
